<template>
  <div v-loading="loading" style="margin: 10px; ">
    <FSection title="关联单据" style="background: white; padding: 10px">
      <template #title>
        <div class="relation-buttons-wrapper">
          <div style="flex: 1">
            关联单据
          </div>
          <el-button style="margin-right: 10px" @click="save"
                     icon="save" round type="primary">保存
          </el-button>
        </div>
      </template>
      <el-form ref="refForm" style="padding: 10px"
               label-width="120px" :model="relation">
        <el-form-item prop="relationName" label="关联名称" :rules="[required]">
          <el-input v-focus placeholder="请输入关联名称" v-model="relation.relationName"/>
        </el-form-item>
        <el-form-item prop="relationName" label="关联标题" :rules="[required]">
          <el-input v-focus placeholder="请输入关联标题" v-model="relation.relationTitle"/>
        </el-form-item>
        <el-form-item prop="originFormName" label="源单据" :rules="[required]">
          <el-select style="width: 100%" @change="relationFormNameChange"
                     v-model="relation.originFormName" :disabled="true">
            <el-option v-for="item in formList" :key="item.formName"
                       :label="item.showName" :value="item.formName"/>
          </el-select>
        </el-form-item>

        <el-form-item prop="relationFormName" label="关联单据" :rules="[required]">
          <el-select style="width: 100%" @change="relationFormNameChange"
                     v-model="relation.relationFormName">
            <el-option v-for="item in formList" :key="item.formName"
                       :label="item.showName" :value="item.formName"/>
          </el-select>
        </el-form-item>

        <el-form-item prop="formName" label="明细域" :rules="[]">
          <el-select style="width: 100%" @change="relationFormsonNameChange"
                     v-model="relation.relationFormsonName" clearable>
            <el-option v-for="item in formsonList" :key="item.formName"
                       :label="item.showName" :value="item.formName"/>
          </el-select>
        </el-form-item>
      </el-form>
    </FSection>

    <FSection title="字段映射" style="background: white; padding: 10px">
      <template #title>
        <HorLayout>
          字段映射
          <template #right>
            <div style="padding-right: 10px">
              <el-button @click="addNewFieldRelation" circle size="small" icon="add"/>
            </div>
          </template>
        </HorLayout>
      </template>

      <HorLayout v-for="(fieldRelation, index) in relation.fieldRelations"
                 style="align-items: center; justify-content: center; margin-bottom: 5px">
        <template #left>
          <el-button icon="document" @click="() => configSelector(fieldRelation)"
                     :type="fieldRelation.selector ? 'primary' : ''" circle size="small"/>
        </template>
        <div style="display: flex; align-items: center; justify-content: center">
          <div style="flex: 0.5">
            <el-select v-model="fieldRelation.originFieldValue"
                       @change="() => originFieldChange(fieldRelation)"
                       style="width: 100%" clearable filterable>
              <el-option v-for="opt in filteredOriginFields" :key="opt.key"
                         :label="opt.showName" :value="opt.key"/>
            </el-select>
          </div>
          <left style="margin: 0 10px"/>
          <div style="flex: 0.5">
            <el-select v-model="fieldRelation.relationFieldValue"
                       @change="() => relationFieldChange(fieldRelation)"
                       style="width: 100%" clearable filterable>
              <el-option v-for="opt in relationFields" :key="opt.key"
                         :label="opt.showName" :value="opt.key"/>
            </el-select>
          </div>
        </div>
        <template #right>
          <div style="padding-right: 10px; height: 100%">
            <el-button circle size="small" @click="() => remove(index)" icon="subtract"/>
          </div>
        </template>
      </HorLayout>
    </FSection>
    <RelationListConfig ref="refRelationListConfig"/>
  </div>
</template>
<script setup>

import {computed, nextTick, ref, shallowRef} from 'vue';
import {getAction, postAction} from '@/request/BaseRequest';
import {isEmpty, isNotEmpty, real, required} from '@/utils/CommonUtils';
import FSection from '@/components/FSection/index.vue';
import HorLayout from '@/components/layout/HorLayout.vue';
import {ElMessage, ElMessageBox} from 'element-plus';
import RelationListConfig from '@/components/app/FormRelation/RelationListConfig/index.vue';

const loading = shallowRef(false);
const relation = ref({
  relationName: undefined,
  relationTitle: undefined,
  originFormName: undefined,
  originFormsonName: undefined,
  relationFormName: undefined,
  relationFormsonName: undefined,
  fieldRelations: []
});
const emits = defineEmits(['saved']);
const refForm = shallowRef();
const formList = shallowRef([]);
const formsonList = shallowRef([]);
const relationFields = shallowRef([]);
const originFields = shallowRef([]);
const refRelationListConfig = shallowRef();

function initPage() {
  formsonList.value = [];
  formList.value = [];
  relationFields.value = [];
  loadDatas();
}

function loadDatas() {
  loadFormDefinitions();
}

function relationFormsonNameChange() {
  loadRelationFields();
}

function addNewFieldRelation() {
  relation.value.fieldRelations.push({
    originFormName: undefined,
    originField: undefined,
    relationFormName: undefined,
    relationField: undefined,
    selector: false,
    relationId: undefined
  });
}

function relationFormNameChange() {
  loading.value = true;
  getAction('/plat/form/loadFormsonDefinitionsByFormName'
    , {formName: real(relation).relationFormName}).then(data => {
    loading.value = false;
    if (data.success) {
      let result = data.result;
      formsonList.value = result;
    }
  });
  loadRelationFields();
}

function loadRelationFields() {
  loading.value = true;
  getAction('/plat/form/loadFormFieldDefinitionForFormRelation', {
    formName: real(relation).relationFormName,
    formsonName: real(relation).relationFormsonName,
  }).then(data => {
    loading.value = false;
    if (data.success) {
      let result = data.result;
      relationFields.value = resolveFields(result);
    }
  });
}

function resolveFields(fields) {
  if (isEmpty(fields)) {
    fields = [];
  }
  fields.forEach(field => {
    field.key = `${field.formName}.${field.tableFieldName}`;
  });
  return fields;
}

function loadFormDefinitions() {
  loading.value = true;
  getAction('/plat/form/loadFormDefinitionForFormRelation').then(data => {
    loading.value = false;
    if (data.success) {
      formList.value = data.result;
    }
  });
}

function addNew(originFormName) {
  initPage();
  initRelation();
  relation.value.originFormName = originFormName;
  loadOriginFields();
}

function loadOriginFields() {
  loading.value = true;
  getAction('/plat/form/loadOriginFormFieldDefinitionForFormRelation', {
    formName: real(relation).originFormName,
  }).then(data => {
    loading.value = false;
    if (data.success) {
      let result = data.result;
      originFields.value = resolveFields(result);
    }
  });
}

function resolveOriginFormsonName() {
  let list = relation.value.fieldRelations;
  if (isNotEmpty(list)) {

    list.forEach(item => {
      item = real(item);
      if (isNotEmpty(item.originFormName)
        && item.originFormName !== relation.value.originFormName) {
        relation.value.originFormsonName = item.originFormName;
      }
    });
  }
}

function relationFieldChange(fieldRelation) {
  nextTick(() => {
    fieldRelation = real(fieldRelation);
    fieldRelation.relationFormName = fieldRelation.relationFieldValue.split('.')[0];
    fieldRelation.relationField = fieldRelation.originFieldValue.split('.')[1];
  });
}

function originFieldChange(fieldRelation) {
  nextTick(() => {
    fieldRelation = real(fieldRelation);
    fieldRelation.originFormName = fieldRelation.originFieldValue.split('.')[0];
    fieldRelation.originField = fieldRelation.originFieldValue.split('.')[1];
    relation.value.originFormsonName = undefined;
    resolveOriginFormsonName();
  });
}

function remove(index) {
  ElMessageBox.confirm('删除后不可恢复, 确定删除吗', {
    draggable: true,
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  }).then(() => {
    relation.value.fieldRelations.splice(index, 1);
  }).catch(() => {
  });
}

const filteredOriginFields = computed(() => {
  if (isEmpty(relation.value.originFormsonName)) return originFields.value;
  let list = [];
  originFields.value.forEach(field => {
    if (field.formName === relation.value.originFormName
      || field.formName === relation.value.originFormsonName) {
      list.push(field);
    }
  });
  return list;
});

function initRelation() {
  relation.value = {
    originFormName: undefined,
    relationFormName: undefined,
    relationFormsonName: undefined,
    fieldRelations: []
  };
}

function configSelector(fieldRelation) {
  let list = relation.value.fieldRelations;
  list.forEach(fr => {
    fr.selector = false;
  });
  fieldRelation.selector = true;
  configList();
}

function configList() {
  refRelationListConfig.value.setData(relation);
}

function getSendData(callback) {
  refForm.value.validate((valid, errors) => {
    if (valid) {
      let data = real(relation);
      if (checkFieldRelation(data)) {
        return callback(data);
      }
    }
  });
}

function checkFieldRelation(data) {
  if (isEmpty(data.fieldRelations)) {
    ElMessage({
      message: '请添加字段映射',
      type: 'warning',
    });
    return undefined;
  }

  for (const index in data.fieldRelations) {
    const fieldRelation = data.fieldRelations[index];
    if (isEmpty(fieldRelation.originFieldValue)
      || isEmpty(fieldRelation.relationFieldValue)) {
      ElMessage({
        message: '请将字段映射必填项填写完整',
        type: 'warning',
      });

      return undefined;
    }
  }

  let flag = false;
  for (const index in data.fieldRelations) {
    const fieldRelation = data.fieldRelations[index];
    if (fieldRelation.selector) {
      flag = true;
    }
  }
  if (!flag) {
    ElMessage({
      message: '请配置段映射列表',
      type: 'warning',
    });
    return false;
  }

  return true;
}

function save() {
  getSendData(data => {
    loading.value = true;
    postAction('/plat/platRelation/saveOrAdd', data).then(data => {
      loading.value = false;
      if (data.success) {
        let result = data.result;
        emits('saved', result);
      }
    });
  });
}

function edit(id) {
  initPage();
  initRelation();
  loading.value = true;
  getAction('/plat/platRelation/loadById', {id}).then(data => {
    loading.value = false;
    if (data.success) {
      relation.value = data.result;
      loadOriginFields();
      relationFormNameChange();
      resolveFieldRelations();
    }
  });
}

function resolveFieldRelations() {
  let list = relation.value.fieldRelations;
  if (isEmpty(list)) {
    relation.value.fieldRelations = list = [];
  }
  list.forEach(item => {
    item.originFieldValue = `${item.originFormName}.${item.originField}`;
    item.relationFieldValue = `${item.relationFormName}.${item.relationField}`;
  });
}

defineExpose({
  edit,
  addNew,
});
</script>
<script>
export default {
  name: 'RelationForm'
};
</script>
<style scoped>
.relation-buttons-wrapper {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
}
</style>
